home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / PCL4C33.ARJ / TERM.C < prev    next >
Text File  |  1992-08-01  |  11KB  |  394 lines

  1. /*
  2. **                    ---  term.c ---
  3. **
  4. **  EXAMPLE CODE: Terminal emulator. Can transfer files using
  5. **  XMODEM, YMODEM, and YMODEM-G protocols.
  6. **
  7. **  See TERM.H for configuration parameters.
  8. **
  9. **  Link with TERM_IO, MODEM_IO, DIR, CRC, DOS, XYMODEM, and XYPACKET.
  10. **  See TERM makefiles.
  11. **
  12. **  Do NOT select YMODEM-G when using a null modem cable unless you are
  13. **  certain that RTS & CTS are reversed ( this is usually not true ).
  14. **
  15. **  This example program (not the PCL4C library) is donated to
  16. **  the Public Domain by MarshallSoft Computing, Inc. It is
  17. **  provided as an example of the use of the PCL4C.
  18. **
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <fcntl.h>
  23. #include <sys\types.h>
  24. #include <sys\stat.h>
  25. #include "pcl4c.h"
  26. #include "ascii.h"
  27. #include "term.h"
  28.  
  29. #define FALSE 0
  30. #define TRUE !FALSE
  31. #define NORMAL 0x07
  32. #define INVERSE 0x70
  33. #define MESSAGE_POS 48
  34.  
  35. void MyCrtWrite();
  36. void MyStart();
  37. void ProcessESC();
  38. void ShowProtocol();
  39. void ShowMessage();
  40. void MyExit();
  41. void SayFilename();
  42. void ErrorCheck();
  43.  
  44. /*** Global variables ***/
  45.  
  46. int Port;               /* current COM port [0..3] */
  47. char Filename[15];      /* file name buffer */
  48. char Buffer[1024];      /* block buffer */
  49. char RxBuf[2048];       /* receive buffer */
  50. char *BaudRate[10] =  {"300","600","1200","2400","4800","9600",
  51.                        "19200","38400","57600","115200"};
  52. int BaudCode;           /* baud rate code ( index into BaudRate[] ) */
  53. char *ModelText[4] = {"Small","Compact","Medium","Large"};
  54. char DTAbuffer[128];
  55. char NCGchar  = NAK;
  56. int OneKflag  = FALSE;
  57. int BatchFlag = FALSE;
  58. char Protocol = 'X';
  59.  
  60. /*** main program ***/
  61.  
  62. main(argc,argv)
  63. int argc;
  64. char *argv[];
  65. {int DataFlag = FALSE;
  66.  char c;
  67.  int i, k;
  68.  int n, rc;
  69.  int Delta;         /* delta port status */
  70.  int Status;        /* port status */
  71.  char Version;
  72.  char temp[81];
  73.  /* right number of parameters ? */
  74.  if(argc!=3)
  75.      {printf("Usage: 'TERM port baud' -- example 'TERM 1 9600'\n");
  76.       exit(1);
  77.      }
  78.  /* get port number from command line */
  79.  Port = atoi(argv[1]) - 1;
  80.  if((Port<0) || (Port>3))
  81.      {printf("Port must be 1 to 4\n");
  82.       exit(1);
  83.      }
  84.  /* get baud rate from command line */
  85.  BaudCode = BaudMatch(argv[2]);
  86.  if(BaudCode<0)
  87.      {printf("Cannot recognize baud rate = %s\n",argv[2]);
  88.       exit(1);
  89.      }
  90.  /* setup transmit & receive buffer */
  91.  ErrorCheck( SioRxBuf(Port,RxBuf,Size2048) );
  92.  /* set parms & reset (initialize) COM port */
  93.  ErrorCheck( SioParms(Port,NoParity,OneStopBit,WordLength8) );
  94.  MyStart(Port,BaudCode);
  95.  /* set DTR and RTS */
  96.  SioDTR(Port,'S');
  97.  SioRTS(Port,'S');
  98.  /* init CRC table */
  99.  InitCRC();
  100.  /* initialize screen */
  101.  Scroll(0,0,24,79,0,NORMAL);
  102.  /* display status message */
  103.  sprintf(temp," COM%d %s %c 'ESC for menu'  ",1+Port,BaudRate[BaudCode],Protocol);
  104.  ShowMessage(0,temp);
  105.  Position(1,0);
  106.  /* display some info */
  107.  puts("TERM 5/1/92");
  108.  Version = SioInfo('V');
  109.  printf("Library = %d.%d\n",Version/16,Version%16);
  110.  printf("Memory Model = %s\n",ModelText[3&SioInfo('M')] );
  111. #if RTS_CTS_CONTROL
  112.  SioFlow(Port,7*ONE_SECOND);
  113.  printf("Flow Control enabled. CTS = ");
  114.  if(SioCTS(Port)) puts("ON");
  115.  else puts("OFF");
  116. #endif
  117.  /* Set FIFO level */
  118.  if( SioFIFO(Port,LEVEL_14) ) puts("INS16550 detected");
  119.  /* clear PCL4C receive buffer */
  120.  ErrorCheck( SioRxFlush(Port) );
  121.  
  122.  /* see TERM.H for definition of AT_COMMAND_SET */
  123. #if AT_COMMAND_SET
  124.  /* wait for Modem to say its ready */
  125.  printf("Waiting for Modem DSR.");
  126.  while( !SioDSR(Port) )
  127.      {
  128.       if(SioKeyPress()||SioBrkKey()) MyExit(0,"Aborted by user");
  129.       putchar('.');
  130.       SioDelay(18);
  131.      }
  132.  putchar('\n');
  133.  /* initialize (Hayes compatible) modem */
  134.  SendTo(Port,"!AT!!~");
  135.  SendTo(Port,"!AT E1 S7=60 S11=60 V1 X1 Q0 S0=1!");
  136.  if(WaitFor(Port,"OK")) printf("\nMODEM READY\n");
  137.  else printf("\nWARNING: Expected OK not received\n");
  138. #endif
  139.  
  140.  /* enter terminal loop */
  141.  SioRxFlush(Port);
  142.  while(1)
  143.      {/* Control-BREAK ? */
  144.       if(SioBrkKey()) MyExit(0,"User pressed Ctrl-BREAK");
  145.       /* was key pressed ? */
  146.       if(SioKeyPress())
  147.           {/* read key press */
  148.            i = SioKeyRead();
  149.            if((char)i==ESC)
  150.                {/* process user's request */
  151.                 ProcessESC();
  152.                 ShowMessage(strlen(BaudRate[BaudCode])+9,"'ESC for Menu' ");
  153.                 continue;
  154.                }
  155.            else PutChar(Port,i);
  156.           }
  157.       /* was break detected ? */
  158.       if( SioBrkSig(Port,'D') ) DisplayLine("BREAK detected ",NULL,0);
  159.       /* any incoming over serial port ? */
  160.       i = GetChar(Port,0);
  161.       if(i>-1)
  162.           {/* good character */
  163.            if(DataFlag&((i<0x20)||(i>0x7e)))
  164.                {MyCrtWrite('^');
  165.                 MyCrtWrite('@'+i);
  166.                }
  167.            else MyCrtWrite(i);
  168.           }
  169.       /* any change in DCD or DSR ? */
  170.       Delta = SioModem(Port,DeltaDCD|DeltaDSR);
  171.       if(Delta)
  172.           {/* display new status */
  173.            Status = SioModem(Port,(char)(DCD|DSR));
  174.            if(!Status&DeltaDCD) MyExit(0,"Dropped DSD");
  175.            if(!Status&DeltaDSR) MyExit(0,"Dropped DSR");
  176.           }
  177.      } /* end -- key pressed */
  178. }
  179.  
  180. /*** write to screen except for bottom line ***/
  181.  
  182. void MyCrtWrite(ch)
  183. char ch;
  184. {/* write character */
  185.  SioCrtWrite(ch);
  186.  /* scroll all but bottom line */
  187.  if(GetRow()==24)
  188.     {Scroll(0,0,23,79,1,NORMAL);
  189.      Position(23,0);
  190.     }
  191. }
  192.  
  193. /*** make multiple attempts to reset port ***/
  194.  
  195. void MyStart(Port,BaudCode)
  196. int Port;
  197. int BaudCode;
  198. {int i, rc;
  199.  /* try up to 3 times to reset COM port */
  200.  for(i=0;i<3;i++)
  201.      {printf("Resetting COM%d at %s baud\n",Port+1,BaudRate[BaudCode]);
  202.       if( (rc = SioReset(Port,BaudCode))==0) return;
  203.       if(rc<0) MyExit(rc,"Error resetting port");
  204.       SioDone(Port);
  205.       /* display errors */
  206.       if(rc&OverrunError) puts("Overrun Error");
  207.       if(rc&ParityError)  puts("Parity Error");
  208.       if(rc&FramingError) puts("Framing Error");
  209.       if(rc&BreakDetect)  puts("Break Detect");
  210.      }
  211.  exit(1);
  212. }
  213.  
  214. /*** find baud rate string in table ***/
  215.  
  216. int BaudMatch(ptr)
  217. char *ptr;
  218. {int i;
  219.  /* find baud rate in table */
  220.  for(i=0;i<10;i++) if(strcmp(BaudRate[i],ptr)==0) return(i);
  221.  return(-1);
  222. }
  223.  
  224. /*** user pressed Escape */
  225.  
  226. void ProcessESC()
  227. {int i;
  228.  int rc;
  229.  int c1, c2;
  230.  char Answer[2]; /* array for 1 char answer */
  231.  int row, col;
  232.  /* user pressed <ESC> */
  233.  Answer[0] = '?';
  234.  Answer[1] = '\0';
  235.  DisplayLine("Q)uit P)rotocol S)end R)eceive: ",Answer,1);
  236.  if(strlen(Answer)) switch(toupper(Answer[0]))
  237.      {
  238.       case 'P':
  239. #if RTS_CTS_CONTROL
  240.           DisplayLine("X) xmodem Y) ymodem G) ymodem-g: ",Answer,1);
  241. #else
  242.           DisplayLine("X) xmodem Y) ymodem: ",Answer,1);
  243. #endif
  244.           if(strlen(Answer)) switch( toupper(Answer[0]) )
  245.                {
  246.                 case 'X':
  247.                     Protocol = 'X';
  248.                     ShowProtocol();
  249.                     OneKflag = FALSE;
  250.                     BatchFlag = FALSE;
  251.                     NCGchar = NAK;
  252.                     DisplayLine("Protocol = XMODEM",NULL,1);
  253.                     break;
  254.                 case 'Y':
  255.                     Protocol = 'Y';
  256.                     ShowProtocol();
  257.                     OneKflag = TRUE;
  258.                     BatchFlag = TRUE;
  259.                     NCGchar = 'C';
  260.                     DisplayLine("Protocol = YMODEM",NULL,1);
  261.                     break;
  262. #if RTS_CTS_CONTROL
  263.                 case 'G':
  264.                     Protocol = 'G';
  265.                     ShowProtocol();
  266.                     OneKflag = TRUE;
  267.                     BatchFlag = TRUE;
  268.                     NCGchar = 'G';
  269.                     DisplayLine("Protocol = YMODEM-G",NULL,1);
  270.                     break;
  271. #endif
  272.                 default:
  273.                     DisplayLine("Must answer X, Y, or G",NULL,1);
  274.                     break;
  275.                }
  276.           break;
  277.       case 'Q':
  278.           MyExit(0,"User pressed ESC");
  279.           break;
  280.       case 'R':
  281.           ShowMessage(strlen(BaudRate[BaudCode])+9,"'CTRL-X aborts'");
  282.           /* XMODEM / YMODEM receive */
  283.           if(BatchFlag)
  284.                {do
  285.                     {/* receive files till get empty filename */
  286.                      RxyModem(Port,Filename,Buffer,NCGchar,BatchFlag);
  287.                      if(SioKeyPress()) break;
  288.                     } while(Filename[0]!='\0');
  289.                }
  290.           else /* not Batch */
  291.                {DisplayLine("Enter filename:",Filename,15);
  292.                 if(strlen(Filename)==0) break;
  293.                 RxyModem(Port,Filename,Buffer,NCGchar,BatchFlag);
  294.                }
  295.           break;
  296.       case 'S':
  297.           ShowMessage(strlen(BaudRate[BaudCode])+9,"'CTRL-X aborts'");
  298.           DisplayLine("Enter filename:",Filename,15);
  299.           if(strlen(Filename)==0) break;
  300.           if(BatchFlag)
  301.                {/* YMODEM send */
  302.                 setDTA(DTAbuffer);
  303.                 if(FindFirst(Filename))
  304.                   {SayFilename(&DTAbuffer[30]);
  305.                    TxyModem(Port,&DTAbuffer[30],Buffer,OneKflag,BatchFlag);
  306.                    while(FindNext())
  307.                      {SioDelay(4);
  308.                       SayFilename(&DTAbuffer[30]);
  309.                       TxyModem(Port,&DTAbuffer[30],Buffer,OneKflag,BatchFlag);
  310.                      }
  311.                    /* send empty filename */
  312.                    Filename[0] = '\0';
  313.                    SioDelay(5);
  314.                    TxyModem(Port,Filename,Buffer,OneKflag,BatchFlag);
  315.                   }
  316.                }
  317.           else
  318.                {/* XMODEM send */
  319.                 TxyModem(Port,Filename,Buffer,OneKflag,BatchFlag);
  320.                }
  321.           break;
  322.      default:
  323.           DisplayLine("Must answer Q, P, S, or R",NULL,0);
  324.           break;
  325.     } /* end switch */
  326. }
  327.  
  328. /*** show protocol choosen ***/
  329.  
  330. void ShowProtocol()
  331. {int SaveRow;
  332.  int SaveCol;
  333.  SaveRow = GetRow();
  334.  SaveCol = GetCol();
  335.  Position(24,MESSAGE_POS+strlen(BaudRate[BaudCode])+7);
  336.  AttrWrite(Protocol,INVERSE);
  337.  Position(SaveRow,SaveCol);
  338. }
  339.  
  340. /*** show chosen message ***/
  341.  
  342. void ShowMessage(Pos,Msg)
  343. int Pos;
  344. char *Msg;
  345. {int i;
  346.  int SaveRow;
  347.  int SaveCol;
  348.  int Col;
  349.  SaveRow = GetRow();
  350.  SaveCol = GetCol();
  351.  Col = MESSAGE_POS+Pos;
  352.  for(i=0;i<strlen(Msg);i++)
  353.    {Position(24,Col++);
  354.     AttrWrite(Msg[i],INVERSE);
  355.    }
  356.  Position(SaveRow,SaveCol);
  357. }
  358.  
  359. /*** exit program ***/
  360.  
  361. void MyExit(code,msg)
  362. int code;
  363. char *msg;
  364. {int rc;
  365.  if(code<0) SioError(code);
  366.  /* Assert UART break & sign off */
  367.  SioBrkSig(Port,'A');
  368.  printf("\nTERMINATING: %s\n",msg);
  369.  SioDelay(ONE_SECOND/2);
  370.  SioDone(Port);
  371.  exit(0);
  372. }
  373.  
  374. /*** display file name in status area ***/
  375.  
  376. void SayFilename(Text)
  377. char *Text;
  378. {char Temp[40];
  379.  strcpy(Temp,"Sending ");
  380.  strcat(Temp,Text);
  381.  DisplayLine(Temp,NULL,0);
  382.  SioDelay(ONE_SECOND/2);
  383. }
  384.  
  385. /*** check for error ***/
  386.  
  387. void ErrorCheck(Code)
  388. int Code;
  389. {/* trap PCL error codes */
  390.  if(Code<0)
  391.      {SioError(Code);
  392.       exit(1);
  393.      }
  394. } /* end ErrorCheck */